package com.leaf.grayrotate;

import java.io.InputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MainSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable{
	
	private SurfaceHolder m_surfaceholder;
	private Thread m_mainthread;
	private boolean m_is_running;
	private Paint m_paint;
	private Canvas m_lockcanvas;
	private int m_screenwidth, m_screenheight;
	private InputStream m_inputstream;
	private Bitmap m_color_bitmap;	
	private Bitmap m_gray_bitmap;
	private float m_touch_x, m_touch_y;
	private boolean m_is_show_gray;
	private int[] m_color_bitmap_data, m_gray_bimap_data;
	private int m_current_bitmap_width, m_current_bitmap_height;
	private Matrix m_matrix;
	private int m_current_angle;

	public MainSurfaceView(Context context) {
		super(context);
		m_surfaceholder = getHolder();
		m_surfaceholder.addCallback(this);
		setFocusable(true);
		m_screenwidth = context.getResources().getDisplayMetrics().widthPixels;
		m_screenheight = context.getResources().getDisplayMetrics().heightPixels;
	}
	
	public void Initialize(){
		//TODO: initialize all variable value here
		try{
			m_inputstream = this.getResources().openRawResource(R.drawable.background);
			m_color_bitmap = BitmapFactory.decodeStream(m_inputstream);
			m_inputstream.close();
		}catch(Exception exc){
			System.out.println("Exc1 " + exc);
		}
		m_is_show_gray = false;		
		m_current_bitmap_width = m_color_bitmap.getWidth();
		m_current_bitmap_height = m_color_bitmap.getHeight();
		m_color_bitmap_data = BitmapToArray(m_color_bitmap);
		m_gray_bimap_data = RGB_To_Gray_Array(m_color_bitmap_data);
		m_gray_bitmap = Bitmap.createBitmap(m_gray_bimap_data, m_current_bitmap_width, m_current_bitmap_height, Bitmap.Config.ARGB_8888);
		m_matrix = new Matrix();
		m_matrix.postTranslate(40, 0);//ini to draw bitmap
		m_current_angle = 0;
		m_paint = new Paint();
		m_mainthread = new Thread(this);
		m_mainthread.start();
		m_is_running = true;
	}
	
	public void GameExit(){
		//TODO destroy all variable here
		m_inputstream = null;
		m_color_bitmap = null;
		m_is_show_gray = false;
		m_current_bitmap_width = 0;
		m_current_bitmap_height = 0;
		m_current_angle = 0;
		m_color_bitmap_data = null;
		m_gray_bimap_data = null;
		m_gray_bitmap = null;
		m_matrix = null;
		m_mainthread = null;		
		m_is_running = false;
		m_screenwidth = 0;
		m_screenheight = 0;
		m_surfaceholder.removeCallback(this);
	}
	
	public void run(){
		while(m_is_running){
			try{
				// Thread.sleep(20);
			}catch(Exception e){}
			GameUpdate();
			m_lockcanvas = m_surfaceholder.lockCanvas(null);
			synchronized (m_surfaceholder) {
				if(m_lockcanvas != null){
					GameDraw(m_lockcanvas);
					m_surfaceholder.unlockCanvasAndPost(m_lockcanvas);
				}
			}
		}
	}
	
	public void GameUpdate(){
		
	}	
	
	
	public void GameDraw(Canvas canvas){
		canvas.drawColor(Color.BLACK);
		if(m_is_show_gray && m_gray_bitmap != null)				
			canvas.drawBitmap(m_gray_bitmap, m_matrix, m_paint);
		else if(m_color_bitmap != null)
			canvas.drawBitmap(m_color_bitmap, m_matrix, m_paint);
		m_paint.setColor(Color.WHITE);
		canvas.drawLine(0, m_screenheight/2, m_screenwidth, m_screenheight/2, m_paint);
		canvas.drawLine(m_screenwidth/2, m_screenheight/2, m_screenwidth/2, m_screenheight, m_paint);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent e){
		super.onTouchEvent(e);
		m_touch_x = e.getX();
		m_touch_y = e.getY();
		if(e.getAction() == MotionEvent.ACTION_UP){
			if(CheckPointInRect(Math.round(m_touch_x), Math.round(m_touch_y), 0, m_screenheight/2, m_screenwidth/2, m_screenheight/2)){				
				m_matrix.reset();//reset the matrix
				m_matrix.postTranslate(-m_color_bitmap.getWidth()/2, -m_color_bitmap.getHeight()/2);//tranlate to center of image
				m_current_angle -= 45;//roate image non clock wise
				if(m_current_angle == 360)
					m_current_angle = 0;
				m_matrix.postRotate(m_current_angle); //rotate image non clock wise
				m_matrix.postTranslate(240, 200);// draw image at the center of image in screen
				m_color_bitmap = Bitmap.createBitmap(m_color_bitmap);//ok if don't have this line
				m_color_bitmap_data = BitmapToArray(m_color_bitmap);
				m_gray_bimap_data = RGB_To_Gray_Array(m_color_bitmap_data);
				m_gray_bitmap = Bitmap.createBitmap(m_gray_bimap_data,  m_current_bitmap_width, m_current_bitmap_height, m_color_bitmap.getConfig());
			}else if(CheckPointInRect(Math.round(m_touch_x), Math.round(m_touch_y), m_screenwidth/2, m_screenheight/2, m_screenwidth/2, m_screenheight/2)){				
				m_matrix.reset();//reset the matrix
				m_matrix.postTranslate(-m_color_bitmap.getWidth()/2, -m_color_bitmap.getHeight()/2);//tranlate to center of image
				m_current_angle += 45;//roate image clock wise
				if(m_current_angle == 360)
					m_current_angle = 0;
				m_matrix.postRotate(m_current_angle);// rotate image clock wise
				m_matrix.postTranslate(240, 200);// draw image at the center of image in screen
				m_color_bitmap = Bitmap.createBitmap(m_color_bitmap);//ok if don't have this line
				m_color_bitmap_data = BitmapToArray(m_color_bitmap);
				m_gray_bimap_data = RGB_To_Gray_Array(m_color_bitmap_data);
				m_gray_bitmap = Bitmap.createBitmap(m_gray_bimap_data,  m_current_bitmap_width, m_current_bitmap_height, m_color_bitmap.getConfig());
			}else{				
				m_is_show_gray = !m_is_show_gray;
			}			
		}
		return true;
	}
	
	private boolean CheckPointInRect(int px, int py, int rx, int ry, int rw, int rh){
		if(px >= rx && px <= (rx + rw) && py >= ry && py <= (ry + rh))
			return true;
		return false;
	}
	
    private int[] RGB_To_Gray_Array(int[] rgb_array){
        int[] gray_array = new int[rgb_array.length];
        int red_fillter_number = Integer.parseInt("00ff0000", 16);
        int green_fillter_number = Integer.parseInt("0000ff00", 16);
        int blue_fillter_number = Integer.parseInt("000000ff", 16);        
        int current_pixel_red_value = 0;
        int current_pixel_green_value = 0;
        int current_pixel_blue_value = 0;
        int current_pixel_gray_value = 0;
        for(int i = 0; i < rgb_array.length; i ++){
            current_pixel_red_value = ((rgb_array[i]&red_fillter_number)>>16);    
            current_pixel_green_value = ((rgb_array[i]&green_fillter_number)>>8);      
            current_pixel_blue_value = (rgb_array[i]&blue_fillter_number);        
            current_pixel_gray_value = (current_pixel_red_value + current_pixel_green_value + current_pixel_blue_value)/3;          
            gray_array[i] = blue_fillter_number;   
            gray_array[i] = (gray_array[i] << 8);          
            gray_array[i] = (gray_array[i]|current_pixel_gray_value);  
            gray_array[i] = (gray_array[i] << 8);
            gray_array[i] = (gray_array[i]|current_pixel_gray_value);              
            gray_array[i] = (gray_array[i] << 8);
            gray_array[i] = (gray_array[i]|current_pixel_gray_value); 
        }
        return gray_array;
    }
	
	private int[] BitmapToArray(Bitmap bitmap_src){
		int [] m_bitmap_data = new int[bitmap_src.getWidth()*bitmap_src.getHeight()];
		for(int i = 0; i < m_bitmap_data.length; i ++){
			m_bitmap_data[i] = 0;
		}
		bitmap_src.getPixels(m_bitmap_data, 0, bitmap_src.getWidth(), 0, 0, bitmap_src.getWidth(), bitmap_src.getHeight());		
		return m_bitmap_data;
	}
	
	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		Initialize();
	}
	
	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
//		m_screenwidth = context.getResources().getDisplayMetrics().widthPixels;
//		m_screenheight = context.getResources().getDisplayMetrics().heightPixels;
	}
	
	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		boolean retry = true;
		m_is_running = false;
        do {
            try {
                m_mainthread.join();
                retry = false;
            } catch (InterruptedException e) {
				e.printStackTrace();
                // we will try it again and again...
            }
        }while(retry);		
	}
}
